home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / groff108.lha / groff-1.08 / libdriver / input.cc next >
C/C++ Source or Header  |  1992-11-25  |  10KB  |  474 lines

  1. // -*- C++ -*-
  2. /* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
  3.      Written by James Clark (jjc@jclark.com)
  4.  
  5. This file is part of groff.
  6.  
  7. groff is free software; you can redistribute it and/or modify it under
  8. the terms of the GNU General Public License as published by the Free
  9. Software Foundation; either version 2, or (at your option) any later
  10. version.
  11.  
  12. groff is distributed in the hope that it will be useful, but WITHOUT ANY
  13. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. You should have received a copy of the GNU General Public License along
  18. with groff; see the file COPYING.  If not, write to the Free Software
  19. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  20.  
  21. #include "driver.h"
  22. #include "device.h"
  23.  
  24. const char *current_filename;
  25. int current_lineno;
  26. const char *device = 0;
  27. FILE *current_file;
  28.  
  29. int get_integer();        // don't read the newline
  30. int possibly_get_integer(int *);
  31. char *get_string(int is_long = 0);
  32. void skip_line();
  33.  
  34. struct environment_list {
  35.   environment env;
  36.   environment_list *next;
  37.  
  38.   environment_list(const environment &, environment_list *);
  39. };
  40.  
  41. environment_list::environment_list(const environment &e, environment_list *p)
  42. : env(e), next(p)
  43. {
  44. }
  45.  
  46. inline int get_char()
  47. {
  48.   return getc(current_file);
  49. }
  50.  
  51. void do_file(const char *filename)
  52. {
  53.   int npages = 0;
  54.   if (filename[0] == '-' && filename[1] == '\0') {
  55.     current_filename = "<standard input>";
  56.     current_file = stdin;
  57.   }
  58.   else {
  59.     errno = 0;
  60.     current_file = fopen(filename, "r");
  61.     if (current_file == 0) {
  62.       error("can't open `%1'", filename);
  63.       return;
  64.     }
  65.     current_filename = filename;
  66.   }
  67.   environment env;
  68.   env.vpos = -1;
  69.   env.hpos = -1;
  70.   env.fontno = -1;
  71.   env.height = 0;
  72.   env.slant = 0;
  73.   environment_list *env_list = 0;
  74.   current_lineno = 1;
  75.   int command;
  76.   char *s;
  77.   command = get_char();
  78.   if (command == EOF)
  79.     return;
  80.   if (command != 'x')
  81.     fatal("the first command must be `x T'");
  82.   s = get_string();
  83.   if (s[0] != 'T')
  84.     fatal("the first command must be `x T'");
  85.   char *dev = get_string();
  86.   if (pr == 0) {
  87.     device = strsave(dev);
  88.     if (!font::load_desc())
  89.       fatal("sorry, I can't continue");
  90.   }
  91.   else {
  92.     if (device == 0 || strcmp(device, dev) != 0)
  93.       fatal("all files must use the same device");
  94.   }
  95.   skip_line();
  96.   env.size = 10*font::sizescale;
  97.   command = get_char();
  98.   if (command != 'x')
  99.     fatal("the second command must be `x res'");
  100.   s = get_string();
  101.   if (s[0] != 'r')
  102.     fatal("the second command must be `x res'");
  103.   int n = get_integer();
  104.   if (n != font::res)
  105.     fatal("resolution does not match");
  106.   n = get_integer();
  107.   if (n != font::hor)
  108.     fatal("horizontal resolution does not match");
  109.   n = get_integer();
  110.   if (n != font::vert)
  111.     fatal("vertical resolution does not match");
  112.   skip_line();
  113.   command = get_char();
  114.   if (command != 'x')
  115.     fatal("the third command must be `x init'");
  116.   s = get_string();
  117.   if (s[0] != 'i')
  118.     fatal("the third command must be `x init'");
  119.   skip_line();
  120.   if (pr == 0)
  121.     pr = make_printer();
  122.   while ((command = get_char()) != EOF) {
  123.     switch (command) {
  124.     case 's':
  125.       env.size = get_integer();
  126.       if (env.height == env.size)
  127.     env.height = 0;
  128.       break;
  129.     case 'f':
  130.       env.fontno = get_integer();
  131.       break;
  132.     case 'C':
  133.       {
  134.     if (npages == 0)
  135.       fatal("`C' command illegal before first `p' command");
  136.     char *s = get_string();
  137.     pr->set_special_char(s, &env);
  138.       }
  139.       break;
  140.     case 'N':
  141.       {
  142.     if (npages == 0)
  143.       fatal("`N' command illegal before first `p' command");
  144.     pr->set_numbered_char(get_integer(), &env);
  145.       }
  146.       break;
  147.     case 'H':
  148.       env.hpos = get_integer();
  149.       break;
  150.     case 'h':
  151.       env.hpos += get_integer();
  152.       break;
  153.     case 'V':
  154.       env.vpos = get_integer();
  155.       break;
  156.     case 'v':
  157.       env.vpos += get_integer();
  158.       break;
  159.     case '0':
  160.     case '1':
  161.     case '2':
  162.     case '3':
  163.     case '4':
  164.     case '5':
  165.     case '6':
  166.     case '7':
  167.     case '8':
  168.     case '9':
  169.       {
  170.     int c = get_char();
  171.     if (!isascii(c) || !isdigit(c))
  172.       fatal("digit expected");
  173.     env.hpos += (command - '0')*10 + (c - '0');
  174.       }
  175.       // fall through
  176.     case 'c':
  177.       {
  178.     if (npages == 0)
  179.       fatal("`c' command illegal before first `p' command");
  180.     int c = get_char();
  181.     if (c == EOF)
  182.       fatal("missing argument to `c' command");
  183.     pr->set_ascii_char(c, &env);
  184.       }
  185.       break;
  186.     case 'n':
  187.       if (npages == 0)
  188.     fatal("`n' command illegal before first `p' command");
  189.       pr->end_of_line();
  190.       (void)get_integer();
  191.       (void)get_integer();
  192.       break;
  193.     case 'w':
  194.     case ' ':
  195.       break;
  196.     case '\n':
  197.       current_lineno++;
  198.       break;
  199.     case 'p':
  200.       if (npages)
  201.     pr->end_page(env.vpos);
  202.       npages++;
  203.       pr->begin_page(get_integer());
  204.       env.vpos = 0;
  205.       break;
  206.     case '{':
  207.       env_list = new environment_list(env, env_list);
  208.       break;
  209.     case '}':
  210.       if (!env_list) {
  211.     fatal("can't pop");
  212.       }
  213.       else {
  214.     env = env_list->env;
  215.     environment_list *tem = env_list;
  216.     env_list = env_list->next;
  217.     delete tem;
  218.       }
  219.       break;
  220.     case 'u':
  221.       {
  222.     if (npages == 0)
  223.       fatal("`u' command illegal before first `p' command");
  224.     int kern = get_integer();
  225.     int c = get_char();
  226.     while (c == ' ')
  227.       c = get_char();
  228.     while (c != EOF) {
  229.       if (c == '\n') {
  230.         current_lineno++;
  231.         break;
  232.       }
  233.       int w;
  234.       pr->set_ascii_char(c, &env, &w);
  235.       env.hpos += w + kern;
  236.       c = get_char();
  237.       if (c == ' ')
  238.         break;
  239.     }
  240.       }
  241.       break;
  242.     case 't':
  243.       {
  244.     if (npages == 0)
  245.       fatal("`t' command illegal before first `p' command");
  246.     int c;
  247.     while ((c = get_char()) != EOF && c != ' ') {
  248.       if (c == '\n') {
  249.         current_lineno++;
  250.         break;
  251.       }
  252.       int w;
  253.       pr->set_ascii_char(c, &env, &w);
  254.       env.hpos += w;
  255.     }
  256.       }
  257.       break;
  258.     case '#':
  259.       skip_line();
  260.       break;
  261.     case 'D':
  262.       {
  263.     if (npages == 0)
  264.       fatal("`D' command illegal before first `p' command");
  265.     int c;
  266.     while ((c = get_char()) == ' ')
  267.       ;
  268.     int n;
  269.     int *p = 0;
  270.     int szp = 0;
  271.     for (int np = 0; possibly_get_integer(&n); np++) {
  272.       if (np >= szp) {
  273.         if (szp == 0) {
  274.           szp = 16;
  275.           p = new int[szp];
  276.         }
  277.         else {
  278.           int *oldp = p;
  279.           p = new int[szp*2];
  280.           memcpy(p, oldp, szp*sizeof(int));
  281.           szp *= 2;
  282.           a_delete oldp;
  283.         }
  284.       }
  285.       p[np] = n;
  286.     }
  287.     pr->draw(c, p, np, &env);
  288.     if (c == 'e') {
  289.       if (np > 0)
  290.         env.hpos += p[0];
  291.     }
  292.     else { 
  293.       for (int i = 0; i < np/2; i++) {
  294.         env.hpos += p[i*2];
  295.         env.vpos += p[i*2 + 1];
  296.       }
  297.       // there might be an odd number of characters
  298.       if (i*2 < np)
  299.         env.hpos += p[i*2];
  300.     }
  301.     a_delete p;
  302.     skip_line();
  303.       }
  304.       break;
  305.     case 'x':
  306.       {
  307.     char *s = get_string();
  308.     int suppress_skip = 0;
  309.     switch (s[0]) {
  310.     case 'i':
  311.       error("duplicate `x init' command");
  312.       break;
  313.     case 'T':
  314.       error("duplicate `x T' command");
  315.       break;
  316.     case 'r':
  317.       error("duplicate `x res' command");
  318.       break;
  319.     case 'p':
  320.       break;
  321.     case 's':
  322.       break;
  323.     case 't':
  324.       break;
  325.     case 'f':
  326.       {
  327.         int n = get_integer();
  328.         char *name = get_string();
  329.         pr->load_font(n, name);
  330.       }
  331.       break;
  332.     case 'H':
  333.       env.height = get_integer();
  334.       if (env.height == env.size)
  335.         env.height = 0;
  336.       break;
  337.     case 'S':
  338.       env.slant = get_integer();
  339.       break;
  340.     case 'X':
  341.       if (npages == 0)
  342.         fatal("`x X' command illegal before first `p' command");
  343.       pr->special(get_string(1), &env);
  344.       suppress_skip = 1;
  345.       break;
  346.     default:
  347.       error("unrecognised x command `%1'", s);
  348.     }
  349.     if (!suppress_skip)
  350.       skip_line();
  351.       }
  352.       break;
  353.     default:
  354.       error("unrecognised command code %1", int(command));
  355.       skip_line();
  356.       break;
  357.     }
  358.   }
  359.   if (npages)
  360.     pr->end_page(env.vpos);
  361. }
  362.  
  363. int get_integer()
  364. {
  365.   int c = get_char();
  366.   while (c == ' ')
  367.     c = get_char();
  368.   int neg = 0;
  369.   if (c == '-') {
  370.     neg = 1;
  371.     c = get_char();
  372.   }
  373.   if (!isascii(c) || !isdigit(c))
  374.     fatal("integer expected");
  375.   int total = 0;
  376.   do {
  377.     total = total*10;
  378.     if (neg)
  379.       total -= c - '0';
  380.     else
  381.       total += c - '0';
  382.     c = get_char();
  383.   }  while (isascii(c) && isdigit(c));
  384.   if (c != EOF)
  385.     ungetc(c, current_file);
  386.   return total;
  387. }
  388.  
  389. int possibly_get_integer(int *res)
  390. {
  391.   int c = get_char();
  392.   while (c == ' ')
  393.     c = get_char();
  394.   int neg = 0;
  395.   if (c == '-') {
  396.     neg = 1;
  397.     c = get_char();
  398.   }
  399.   if (!isascii(c) || !isdigit(c)) {
  400.     if (c != EOF)
  401.       ungetc(c, current_file);
  402.     return 0;
  403.   }
  404.   int total = 0;
  405.   do {
  406.     total = total*10;
  407.     if (neg)
  408.       total -= c - '0';
  409.     else
  410.       total += c - '0';
  411.     c = get_char();
  412.   }  while (isascii(c) && isdigit(c));
  413.   if (c != EOF)
  414.     ungetc(c, current_file);
  415.   *res = total;
  416.   return 1;
  417. }
  418.  
  419.  
  420. char *get_string(int is_long)
  421. {
  422.   static char *buf;
  423.   static int buf_size;
  424.   int c = get_char();
  425.   while (c == ' ')
  426.     c = get_char();
  427.   for (int i = 0;; i++) {
  428.     if (i >= buf_size) {
  429.       if (buf_size == 0) {
  430.     buf_size = 16;
  431.     buf = new char[buf_size];
  432.       }
  433.       else {
  434.     char *old_buf = buf;
  435.     int old_size = buf_size;
  436.     buf_size *= 2;
  437.     buf = new char[buf_size];
  438.     memcpy(buf, old_buf, old_size);
  439.     a_delete old_buf;
  440.       }
  441.     }
  442.     if ((!is_long && (c == ' ' || c == '\n')) || c == EOF) {
  443.       buf[i] = '\0';
  444.       break;
  445.     }
  446.     if (is_long && c == '\n') {
  447.       current_lineno++;
  448.       c = get_char();
  449.       if (c == '+')
  450.     c = '\n';
  451.       else {
  452.     buf[i] = '\0';
  453.     break;
  454.       }
  455.     }  
  456.     buf[i] = c;
  457.     c = get_char();
  458.   }
  459.   if (c != EOF)
  460.     ungetc(c, current_file);
  461.   return buf;
  462. }
  463.  
  464. void skip_line()
  465. {
  466.   int c;
  467.   while ((c = get_char()) != EOF)
  468.     if (c == '\n') {
  469.       current_lineno++;
  470.       break;
  471.     }
  472. }
  473.  
  474.